/**
 * @author YJSYS
 *
 */

package com.qd.extcam;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import android.hardware.Camera;
import android.media.MediaRecorder;
import android.view.SurfaceHolder;

public class ExtRecorder extends MediaRecorder {
	private ExtCamActivity activity;
	private Camera camera;
	private SurfaceHolder sh;
	private String sensorFileName;
	private String locationFileName;
	private String mediaFileName;

	/** ExtRecorder 생성자
	 * @param sh
	 */
	public ExtRecorder(ExtCamActivity activity, SurfaceHolder sh) {
		this.activity = activity;
		this.sh = sh;
	}

	/** 녹화를 시작하기전 초기화 작업을 한다.
	 * MediaRecorder에 대한 초기화 작업이 진행된다.
	 * @param fileName 녹화 파일 명
	 */
	public void InitMediaRecorder(String fileName) {
		// Step 1: Unlock and set camera to MediaRecorder
		camera = Camera.open();
		camera.unlock();
		// camera.setDisplayOrientation(180);
		super.setCamera(camera);
		// super.setOnInfoListener(m_listener);
		super.setMaxFileSize(Long.MAX_VALUE);

		super.setAudioSource(MediaRecorder.AudioSource.MIC);
		super.setVideoSource(MediaRecorder.VideoSource.CAMERA);

		// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
		// super.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
		super.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
		super.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
		super.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
		super.setVideoSize(640, 480);
		super.setVideoFrameRate(30);

		/*
		 * 19000K HD
		 */
		super.setVideoEncodingBitRate(1920 * 1000);

		mediaFileName = ExtCamActivity.EXTCAM_DIR + File.separator + fileName + ".mp4";
		super.setOutputFile(mediaFileName);
		super.setPreviewDisplay(sh.getSurface());
	}

	/** 녹화를 마친후 센서 정보를 병합하기 위한 센서파일의 위치를 지정한다.
	 * @param fileName 센서 파일명
	 */
	public void setSensorFile(String fileName) {
		sensorFileName = fileName;
	}

	/** 녹화를 마친후 위치 정보를 병합하기 위한 위치정보파일의 위치를 지정한다.
	 * @param fileName 위치정보 파일명
	 */
	public void setLocationFile(String fileName) {
		locationFileName = fileName;
	}

	/* (non-Javadoc)
	 * @see android.media.MediaRecorder#prepare()
	 */
	public void prepare() {
		try {
			super.prepare();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/* (non-Javadoc)
	 * @see android.media.MediaRecorder#start()
	 */
	public void start() {
		super.start();
	}

	/* (non-Javadoc)
	 * @see android.media.MediaRecorder#stop()
	 */
	public void stop() {
		super.stop();
		this.camera.release();
		super.release();
		mergeFile(true);
	}

	/** 녹화 종료후 센서 파일과 위치정보 파일을 동영상 파일에 병합한다.
	 * @param isDelete
	 */
	private void mergeFile(boolean isDelete) {
		File mFile = new File(mediaFileName);
		File sFile = new File(sensorFileName);
		File lFile = new File(locationFileName);
		FileOutputStream fos = null;
		FileInputStream fis1 = null;
		FileInputStream fis2 = null;

		try {
			fos = new FileOutputStream(mFile, true);
			long sensor_pos = 0, gps_pos = 0;

			if (sFile.exists()) {
				fis1 = new FileInputStream(sFile);
				sensor_pos = mFile.length();
				if (fos != null && fis1 != null) {
					byte[] buffer = new byte[1024];
					int readLength = 0;
					while ((readLength = fis1.read(buffer)) > 0) {
						fos.write(buffer, 0, readLength);
					}
				}
			}

			if (lFile.exists()) {
				fis2 = new FileInputStream(lFile);
				gps_pos = mFile.length();
				if (fos != null && fis2 != null) {
					byte[] buffer = new byte[1024];
					int readLength = 0;
					while ((readLength = fis2.read(buffer)) > 0) {
						fos.write(buffer, 0, readLength);
					}
					
					String strRange = "#Latitude:" + activity.getMinLatitude() + "," + activity.getMaxLatitude() + "\n";
					fos.write(strRange.getBytes());
					strRange = "#Longitude:" + activity.getMinLongitude() + "," + activity.getMaxLongitude() + "\n";
					fos.write(strRange.getBytes());
				}
			}

			String sTag = "SVAL";
			fos.write(sTag.getBytes());
			byte[] sb = toByteArray(sensor_pos);
			fos.write(sb);

			sTag = "GVAL";
			fos.write(sTag.getBytes());
			fos.write(toByteArray(gps_pos));

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (fos != null)
					fos.close();
				if (fis1 != null)
					fis1.close();
				if (isDelete) {
					if (sFile != null && sFile.exists())
						sFile.delete();
					if (lFile != null && lFile.exists())
						lFile.delete();					
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static byte[] toByteArray(long value)    
	{  
		ByteBuffer bb = ByteBuffer.allocate(8);  
		return bb.putLong(value).array();  
	}
}
